package cn.edu.tju.wallet.domain;

import cn.edu.tju.core.model.BaseEntity;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 充值规则实体（充血模型）
 * 包含规则数据和规则相关的业务逻辑
 */
@Entity
@Table(name = "recharge_rules")
public class RechargeRule extends BaseEntity {

    @Column(name = "name", nullable = false, length = 100)
    private String name; // 规则名称

    @Column(name = "min_amount", precision = 19, scale = 2, nullable = false)
    private BigDecimal minAmount; // 最小充值金额

    @Column(name = "bonus_rate", precision = 5, scale = 4)
    private BigDecimal bonusRate; // 奖励比例

    @Column(name = "bonus_amount", precision = 19, scale = 2)
    private BigDecimal bonusAmount; // 奖励金额

    @Column(name = "start_time", nullable = false)
    private LocalDateTime startTime; // 开始时间

    @Column(name = "end_time")
    private LocalDateTime endTime; // 结束时间

    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false, length = 20)
    private RuleStatus status = RuleStatus.ACTIVE; // 规则状态

    @Column(name = "priority", nullable = false)
    private Integer priority = 0; // 优先级

    @Column(name = "comment", length = 500)
    private String comment; // 规则描述

    // ============================================
    // 构造函数
    // ============================================

    public RechargeRule() {}

    public RechargeRule(String name, BigDecimal minAmount, BigDecimal bonusAmount) {
        this.name = name;
        this.minAmount = minAmount;
        this.bonusAmount = bonusAmount;
        this.startTime = LocalDateTime.now();
        this.status = RuleStatus.ACTIVE;
        this.priority = 0;
    }

    public RechargeRule(String name, BigDecimal minAmount, BigDecimal bonusAmount, String comment) {
        this.name = name;
        this.minAmount = minAmount;
        this.bonusAmount = bonusAmount;
        this.comment = comment;
        this.startTime = LocalDateTime.now();
        this.status = RuleStatus.ACTIVE;
        this.priority = 0;
    }

    // ============================================
    // 核心业务方法
    // ============================================

    /**
     * 判断规则是否适用（充血模型：规则自己判断自己的适用性）
     * @param amount 充值金额
     * @return 是否适用
     */
    public boolean isApplicable(BigDecimal amount) {
        if (this.status != RuleStatus.ACTIVE) return false;

        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(this.startTime)) return false;

        if (this.endTime != null && now.isAfter(this.endTime)) return false;

        return amount.compareTo(this.minAmount) >= 0;
    }

    /**
     * 计算奖励金额（充血模型：规则自己计算奖励）
     * @param amount 充值金额
     * @return 奖励金额
     */
    public BigDecimal calculateBonus(BigDecimal amount) {
        if (!isApplicable(amount)) return BigDecimal.ZERO;

        // 优先使用固定奖励金额
        if (this.bonusAmount != null && this.bonusAmount.compareTo(BigDecimal.ZERO) > 0)
            return this.bonusAmount;

        // 使用比例奖励
        if (this.bonusRate != null && this.bonusRate.compareTo(BigDecimal.ZERO) > 0)
            return amount.multiply(this.bonusRate);

        return BigDecimal.ZERO;
    }

    /**
     * 判断规则是否激活
     * @return 是否激活
     */
    public boolean isActive() {
        return this.status == RuleStatus.ACTIVE;
    }

    /**
     * 判断规则是否已过期
     * @return 是否过期
     */
    public boolean isExpired() {
        return this.endTime != null && LocalDateTime.now().isAfter(this.endTime);
    }

    /**
     * 判断规则是否尚未开始
     * @return 是否尚未开始
     */
    public boolean isNotStarted() {
        return LocalDateTime.now().isBefore(this.startTime);
    }

    /**
     * 判断规则是否有效（在有效期内且状态为激活）
     * @return 是否有效
     */
    public boolean isValid() {
        return isActive() && !isExpired() && !isNotStarted();
    }

    /**
     * 获取规则的有效性描述
     * @return 有效性描述
     */
    public String getValidityDescription() {
        if (status != RuleStatus.ACTIVE) {
            return "规则未激活";
        }
        if (isNotStarted()) {
            return "规则尚未开始";
        }
        if (isExpired()) {
            return "规则已过期";
        }
        return "规则有效";
    }

    /**
     * 激活规则
     * @return 当前规则对象
     */
    public RechargeRule activate() {
        this.status = RuleStatus.ACTIVE;
        return this;
    }

    /**
     * 停用规则
     * @return 当前规则对象
     */
    public RechargeRule deactivate() {
        this.status = RuleStatus.INACTIVE;
        return this;
    }

    /**
     * 设置规则的有效期
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 当前规则对象
     */
    public RechargeRule setValidityPeriod(LocalDateTime startTime, LocalDateTime endTime) {
        this.startTime = startTime;
        this.endTime = endTime;
        return this;
    }

    /**
     * 设置优先级
     * @param priority 优先级（数字越大优先级越高）
     * @return 当前规则对象
     */
    public RechargeRule setPriority(Integer priority) {
        this.priority = priority;
        return this;
    }

    /**
     * 获取奖励类型描述
     * @return 奖励类型描述
     */
    public String getBonusTypeDescription() {
        if (this.bonusAmount != null && this.bonusAmount.compareTo(BigDecimal.ZERO) > 0) {
            return "固定奖励 " + this.bonusAmount + " 元";
        } else if (this.bonusRate != null && this.bonusRate.compareTo(BigDecimal.ZERO) > 0) {
            return "比例奖励 " + (this.bonusRate.multiply(BigDecimal.valueOf(100))) + "%";
        } else {
            return "无奖励";
        }
    }

    /**
     * 获取奖励条件描述
     * @return 奖励条件描述
     */
    public String getConditionDescription() {
        return "单笔充值满 " + this.minAmount + " 元";
    }

    /**
     * 计算总到账金额（充值金额 + 奖励金额）
     * @param amount 充值金额
     * @return 总到账金额
     */
    public BigDecimal calculateTotalAmount(BigDecimal amount) {
        BigDecimal bonus = calculateBonus(amount);
        return amount.add(bonus);
    }

    /**
     * 计算奖励收益率（奖励金额/充值金额）
     * @param amount 充值金额
     * @return 收益率（百分比）
     */
    public BigDecimal calculateBonusRate(BigDecimal amount) {
        BigDecimal bonus = calculateBonus(amount);
        if (amount.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO;
        return bonus.divide(amount, 4, java.math.RoundingMode.HALF_UP)
                  .multiply(BigDecimal.valueOf(100));
    }

    /**
     * 验证规则参数的有效性
     * @throws IllegalArgumentException 当参数无效时
     */
    public void validate() {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("规则名称不能为空");
        }
        if (minAmount == null || minAmount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("最小充值金额必须大于0");
        }
        if (bonusAmount == null && bonusRate == null) {
            throw new IllegalArgumentException("必须设置奖励金额或奖励比例至少一个");
        }
        if (bonusAmount != null && bonusAmount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("奖励金额不能为负数");
        }
        if (bonusRate != null && (bonusRate.compareTo(BigDecimal.ZERO) < 0 || bonusRate.compareTo(BigDecimal.ONE) > 0)) {
            throw new IllegalArgumentException("奖励比例必须在0到1之间");
        }
        if (startTime == null) {
            throw new IllegalArgumentException("开始时间不能为空");
        }
        if (endTime != null && endTime.isBefore(startTime)) {
            throw new IllegalArgumentException("结束时间不能早于开始时间");
        }
    }

    /**
     * 判断是否可以删除规则
     * @return 是否可以删除
     */
    public boolean canBeDeleted() {
        // 只有未激活的规则才能删除
        return this.status == RuleStatus.INACTIVE;
    }

    /**
     * 获取规则的详细信息描述
     * @return 规则描述
     */
    public String getDescription() {
        if (comment != null && !comment.trim().isEmpty()) {
            return comment;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(name).append("：");
        sb.append(getConditionDescription()).append("，");
        sb.append(getBonusTypeDescription());
        sb.append("，状态：").append(getValidityDescription());
        return sb.toString();
    }

    // ============================================
    // Getter and Setter
    // ============================================

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getMinAmount() {
        return minAmount;
    }

    public void setMinAmount(BigDecimal minAmount) {
        this.minAmount = minAmount;
    }

    public BigDecimal getBonusRate() {
        return bonusRate;
    }

    public void setBonusRate(BigDecimal bonusRate) {
        this.bonusRate = bonusRate;
    }

    public BigDecimal getBonusAmount() {
        return bonusAmount;
    }

    public void setBonusAmount(BigDecimal bonusAmount) {
        this.bonusAmount = bonusAmount;
    }

    public LocalDateTime getStartTime() {
        return startTime;
    }

    public void setStartTime(LocalDateTime startTime) {
        this.startTime = startTime;
    }

    public LocalDateTime getEndTime() {
        return endTime;
    }

    public void setEndTime(LocalDateTime endTime) {
        this.endTime = endTime;
    }

    public RuleStatus getStatus() {
        return status;
    }

    public void setStatus(RuleStatus status) {
        this.status = status;
    }

    public Integer getPriority() {
        return priority;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }


    // 规则状态
    public enum RuleStatus {
        ACTIVE,     // 激活
        INACTIVE    // 未激活
    }
}

